Skip to content

Harness Engineering ​

标签
AI/agent/Harness
字数
4516 字
阅读时间
18 分钟

围绕 AI Agent 设计约束、工具、验证机制与反馈回路,让它在生产环境里可靠完成任务的工程实践。管理的是模型之外的一切。

一句话概括:Agent = Model + Harness。

Harness 本意是马具,指套在马身上、用来传递力量和控制方向的那套装备。换成工程语言,Harness 是 Agent 的运行外壳——它决定 Agent 记住什么、看到什么上下文、能调用什么工具、被允许做什么、出错之后发生什么。

一句话定调:「今天的模型能做的」和「你看到它们做的」之间的差距,大部分是 harness 差距,不是模型差距。

时间线 ​

时间事件
2026-02-05Mitchell Hashimoto(HashiCorp 联合创始人,Terraform 作者)在博客《My AI Adoption Journey》中给这件事命名
2026-02-11OpenAI 工程师 Ryan Lopopolo 发布《Harness engineering: leveraging Codex in an agent-first world》
2026-02-17Birgitta Böckeler(Thoughtworks Distinguished Engineer)在 martinfowler.com 首发备忘录
2026-04-02同一作者发表完整文章《Harness Engineering: Guides and Sensors for Coding Agents》
2026-09-02Google 团队在 DEV Community 发文,给出基于 Google ADK 2.0 的最小实现

Hashimoto 的定义值得逐字记住:

anytime you find an agent makes a mistake, you take the time to engineer a solution such that the agent never makes that mistake again.

也就是:Agent 每犯一次错,就动一次环境,让这类错误在结构上不再可能发生。把「我希望它这样做」变成「它不可能那样做」。

Lopopolo 公开的内部实验数据:一个 3 人团队从 2025 年 8 月底的空仓库开始,5 个月内由 Codex 生成约 100 万行代码、合并约 1500 个 PR,应用逻辑、测试、CI 配置、文档、可观测性全部零手写。人在这套流程里做的是设计环境、定义意图、搭反馈回路。

三个同心圆:harness 是哪一层 ​

「harness」这个词在不同尺度上被使用,不分开就会打架。Böckeler 用同心圆把边界画清了:

   ┌─────────────────────────────────────────────────────────┐
   │ 用户 harness(你建的)                                     │
   │   AGENTS.md · skills · hooks · 自定义 linter ·             │
   │   review agent · CI sensors                              │
   │                                                          │
   │   ┌─────────────────────────────────────────────────┐    │
   │   │ Builder harness(agent 厂商建的)                  │    │
   │   │   system prompt · 工具集 · 检索机制                │    │
   │   │                                                  │    │
   │   │   ┌─────────────────────────────────────────┐    │    │
   │   │   │ Model(被驾驭的东西)                     │    │    │
   │   │   └─────────────────────────────────────────┘    │    │
   │   └─────────────────────────────────────────────────┘    │
   └─────────────────────────────────────────────────────────┘

   Model          是内核
   内层 harness   厂商围绕它建(system prompt、工具集、代码检索机制)
   外层 harness   你围绕内层建,为自己的代码库定制

Harness Engineering 讲的基本都是最外那一圈。建得好的外层 harness 做两件事:
   ① 提高 agent 第一次就做对的概率
   ② 提供自我修正的反馈回路,让很多问题在到达人之前就被处理掉
      └─ 减少审查负担、提高质量、少烧 token
  • Model 是内核
  • 厂商围绕它建内层 harness(system prompt、工具集、代码检索机制)
  • 你围绕内层建外层 harness,为自己的代码库定制

Harness Engineering 讲的基本都是最外那一圈。 建得好的外层 harness 做两件事:提高 agent 第一次就做对的概率,以及提供一个自我修正的反馈回路,让很多问题在到达人之前就被处理掉——减少审查负担、提高质量、少烧 token。

两条正交的轴:Guides 与 Sensors ​

Böckeler 的核心贡献是一套从控制论借来的词汇。harness 像一个调速器(governor),用两类控制把代码库调向期望状态:

类型时机作用例子
Guides(前馈控制)agent 行动之前预测它的行为并引导它,提高一次做对的概率编码约定文档、AGENTS.md、skills、参考文档、how-to 指南、codemod
Sensors(反馈控制)agent 行动之后观测结果并帮它自我修正类型检查、linter、测试、静态分析、AI review agent

两者缺一不可,原因很直白:

  • 只有 guides 没有 sensors —— harness「编码了规则,却永远不知道规则是否奏效」
  • 只有 sensors 没有 guides —— agent「一直重复同样的错误再修正」

harness 像一个调速器,用两类控制把代码库调向期望状态。

   Guides(前馈控制)              Sensors(反馈控制)
   时机:agent 行动之前             时机:agent 行动之后
   作用:预测它的行为并引导它,       作用:观测结果并帮它自我修正
        提高一次做对的概率
   例子:编码约定文档 / AGENTS.md /  例子:类型检查 / linter / 测试 /
        skills / 参考文档 /         静态分析 / AI review agent
        how-to 指南 / codemod

        └────────── 两者缺一不可 ──────────┘
   只有 guides 没有 sensors
      └─ harness「编码了规则,却永远不知道规则是否奏效」
   只有 sensors 没有 guides
      └─ agent「一直重复同样的错误再修正」

每种控制又有两种执行形态,按需选而不是越强越好
   Computational(确定性)
     快、便宜、可预测、CPU 跑;成本在毫秒到秒级
     └─ linter、结构测试、格式检查、类型检查
   Inferential(推理性)
     语义理解强、较慢、非确定性;成本高
     └─ LLM-as-a-judge、风格审查、需求符合度检查
   └─ 确定性检查放在最前面(快且可靠),
      推理性检查放在后面(贵,但能做 linter 做不到的判断)

一个精妙的设计:让 sensor 说模型能听懂的话
   一条自定义 linter 消息不只说「error」,而是包含怎么修的指令。
   Böckeler 称这个叫「一种正向的 prompt injection」——
   sensor 用 agent 能行动的语言对它说话。
   └─ 同一个原理在别处也出现过:ReAct 把解析失败的错误信息塞回历史、
      Function Calling 校验失败返回描述性错误而不是抛异常。
      错误信息是给模型的输入,所以要按输入的规格来写。

每种控制又有两种执行形态 ​

形态特性成本例子
Computational(确定性)快、便宜、可预测、CPU 跑低(毫秒到秒级)linter、结构测试、格式检查、类型检查
Inferential(推理性)语义理解强、较慢、非确定性高LLM-as-a-judge、风格审查、需求符合度检查

这一栏要按需选,不是越强越好——确定性检查放在最前面(快且可靠),推理性检查放在后面(贵但能做 linter 做不到的判断)。

一个精妙的设计:让 sensor 说模型能听懂的话 ​

最好的 sensors 产出的反馈是「为模型消费优化」的。

具体做法:一条自定义 linter 消息不只说「error」,而是包含怎么修的指令。Böckeler 称这个叫「一种正向的 prompt injection」——sensor 用 agent 能行动的语言对它说话。

这条经验在其他地方也出现过:03-ReAct 里解析失败要把错误信息作为 Observation 塞回历史;Function Calling 里校验失败要返回描述性错误而不是抛异常。同一个原理:错误信息是给模型的输入,所以要按输入的规格来写。

三类调控目标:难度差了一个数量级 ​

类型管什么成熟度
可维护性 harness内部代码质量最容易——工具成熟(linter、复杂度分析、测试覆盖)
架构适配 harness性能、可观测性等架构特性(Fowler 的 fitness functions)中
行为 harness应用是否真的做了它该做的事最难——「房间里的大象」,基本未解

第三类为什么难:AI 生成的测试套件目前还不够可靠(见 AI Coding 工作流 里那条「覆盖率 90% 但只测了 happy path」)。用模型验证模型,会撞上同源盲区——这是 LLM Evaluation 与反馈闭环 要单独处理的问题。

三类调控目标,难度差了一个数量级。

   ┌──────────────────────────────────────────────────────────┐
   │ 可维护性 harness    管内部代码质量                          │
   │   成熟度:最容易 —— 工具成熟                               │
   │   (linter、复杂度分析、测试覆盖)                          │
   └──────────────────────────────────────────────────────────┘
   ┌──────────────────────────────────────────────────────────┐
   │ 架构适配 harness    管性能、可观测性等架构特性                │
   │   (Fowler 的 fitness functions)                          │
   │   成熟度:中                                               │
   └──────────────────────────────────────────────────────────┘
   ┌──────────────────────────────────────────────────────────┐
   │ 行为 harness        管应用是否真的做了它该做的事              │
   │   成熟度:最难 ——「房间里的大象」,基本未解                   │
   └──────────────────────────────────────────────────────────┘

   第三类为什么难
     AI 生成的测试套件目前还不够可靠
     (对应 AI Coding 工作流那篇里「覆盖率 90% 但只测了 happy path」)
     └─ 用模型验证模型,会撞上同源盲区 ——
        这是 LLM Evaluation 与反馈闭环要单独处理的问题

Shift left ​

控制要尽可能地往生命周期的前段放:

   控制要尽可能地往生命周期的前段放

   commit 前  ──▶ linter、单元测试              快、便宜
        │
        ▼
   集成前     ──▶ 类型检查、结构测试
        │
        ▼
   流水线     ──▶ 变异测试、架构审查              贵
        │
        ▼
   持续监控   ──▶ 代码漂移、生产指标

   └─ 越早发现越便宜修 —— 这是 CI 的老直觉,现在用在 agent 的产出上

越早发现越便宜修——这是 CI 的老直觉,现在用在 agent 的产出上。

Ashby 定律与 harnessability ​

Ashby 的必要多样性定律:调控器必须至少有被调控系统的多样性。

因为 LLM 几乎能产出任何东西(多样性极高),承诺一个受约束的架构就是一个降多样性的动作——固定拓扑、可预测结构,能让一个完整的 harness 变得可达。

由此推出 harnessability(可驾驭性):不是所有代码库都同样可被驾驭。

更好驾驭更难驾驭
强类型语言动态类型
抽象框架(如 Spring)手写胶水代码
清晰的模块边界边界模糊
——债台高筑的遗留代码

最后那一格有个讽刺:遗留系统最难被驾驭,但它最需要。

配套概念还有两个:ambient affordances(Ned Letcher)——环境里那些让 agent 读得懂、走得通的结构性属性;harness templates——把现有的服务模板演进成「每种拓扑一套 guides + sensors」的捆绑(dashboard / CRUD / event processor 这几类是多数企业的主力拓扑)。

Harness 的结构 ​

按执行、控制、状态切三层:

工具与执行层。 读写文件、调用 Bash、访问 API、操作浏览器——工具的定义和授权。工具表面越清晰,Agent 行为越可预期。

控制与验证层。 这是 Harness 区别于 Prompt 工程的核心。对照一下:让 Agent「请遵守代码规范」,依赖的是概率性合规;接一个违反规范就阻断 PR 的 Linter,属于确定性结构约束。测试套件、类型检查、权限边界、审批门控接进来之后,这类错误从概率上的减少变成结构上的关闭——它不再有机会进入主干。

持久化与状态层。 长任务的瓶颈是上下文窗口一满,之前的工作就丢了。用文件系统和 Git 把状态落盘,Agent 才可能从中断处续跑。

另一套流传较广的划分是三个支柱:上下文工程(在正确的时间给出正确的信息,包括 AGENTS.md、架构规范、测试结果)、架构约束(代码规范检查器、自动化测试强制边界)、熵管理(定期清理 AI 生成代码里积累的过时文档、命名偏差、死代码)。

「三大支柱」这套说法来自中文技术自媒体,与 Böckeler 的 guides / sensors 框架并非同一套划分,未见官方对应,标为待验证。

按执行、控制、状态切三层。

   ┌──────────────────────────────────────────────────────────┐
   │ 工具与执行层                                               │
   │   读写文件、调用 Bash、访问 API、操作浏览器 —— 工具定义与授权  │
   │   └─ 工具表面越清晰,Agent 行为越可预期                      │
   └──────────────────────────────────────────────────────────┘
   ┌──────────────────────────────────────────────────────────┐
   │ 控制与验证层(Harness 区别于 Prompt 工程的核心)              │
   │   对照:让 Agent「请遵守代码规范」          → 概率性合规       │
   │         接一个违反规范就阻断 PR 的 Linter   → 确定性约束       │
   │   测试套件 / 类型检查 / 权限边界 / 审批门控接进来之后,
   │   这类错误从「概率上的减少」变成「结构上的关闭」——
   │   它不再有机会进入主干                                      │
   └──────────────────────────────────────────────────────────┘
   ┌──────────────────────────────────────────────────────────┐
   │ 持久化与状态层                                             │
   │   长任务的瓶颈是上下文窗口一满、之前的工作就丢了               │
   │   └─ 用文件系统和 Git 把状态落盘,Agent 才可能从中断处续跑     │
   └──────────────────────────────────────────────────────────┘

另一套流传较广的划分是三个支柱:上下文工程 / 架构约束 / 熵管理。
   └─ 这套说法来自中文技术自媒体,与 Böckeler 的 guides / sensors
      并非同一套划分,未见官方对应,标为待验证

具体的实现组件 ​

LangChain 公开的 harness 组件里有两个值得记的:

组件解决什么
LocalContextMiddleware把环境信息在起始阶段就注入——这是 Guides 一侧的典型做法
LoopDetectionMiddlewareagent 会卡在重复循环里——有时对同一个文件做 10 次以上微小修改,每次都是同样的失败路径。这个 middleware 追踪每个文件的编辑次数,超过阈值就注入提示,让 agent 重新思考策略

LoopDetectionMiddleware 是 Agent Loop 里「重复动作检测」的一个具体实现——区别在于它检测的粒度是「同一文件被反复改」,而不是「同一工具被反复调」。后者看不出来的循环,前者能看出来。

一组值得记的对照数据:LangChain 团队用同一个模型(Claude Opus 4.6)测试,在早期版本的 harness 下跑出 59.6%——有竞争力但不如 Codex。原因是那个 harness 还没跑过同等轮次的迭代改善循环,而不是模型差。

OpenAI 那边的做法是:自定义 linter + 结构测试 + 「垃圾回收」(后者的目标对应上面说的「熵管理」)。

规则的分层 ​

常见的分层方式是:

text
Global Rules        全局,跨项目的个人/团队偏好
Project Rules       项目级约束
Repository Rules    仓库级约束
Task Rules          单次任务约束

载体通常落在 Agent 的全局配置和仓库根目录,AGENTS.md 是目前跨工具通用性最好的一个(Codex、Claude Code、WorkBuddy 等都原生识别)。AGENTS.md 的内容属于 Context 层,而它约束的东西能不能被强制执行,取决于 Harness 层有没有对应的检查器。

一条不能忘的边界 ​

harness 不能可靠地捕获高层问题——误诊(诊断错了病因)、过度工程、误解指令,这三类都拦不住。

人类经验仍然是一个不可替代的「隐式 harness」。

目标是把人的注意力导向最重要的地方,而不是消灭人——这也和 LLM Evaluation 与反馈闭环 里「减少人需要 review 的数据量」是同一个思路。

Harness Engineering 是一个持续的工程实践,不是一次性的配置。 它和 Context Engineering 的关系是:harness engineering 是应用于编码 agent 的一种特定形式的上下文工程。

与 Prompt / Context Engineering 的层次关系 ​

三个概念叠在一起,不是互相替代:

维度Prompt EngineeringContext EngineeringHarness Engineering
核心问题这句话怎么措辞模型看到哪些信息整个系统怎么运转
作用范围单条提示一次调用的全部输入工具 + 权限 + 验证 + 状态 + 可观测性
作用时间编写时一次性确定运行时逐轮组装跨全部轮次持续生效
失效信号输出含糊、格式错乱缺背景、答非所问多步崩溃、死循环、结果不可预测
修复手段改措辞重组输入重设计系统架构

这个划分能当诊断工具用:单步任务输出含糊 → 改提示;答错方向、缺关键背景 → 调输入组装;多步任务中途崩溃或反复循环 → 提示词改多少遍都没用,问题是缺验证回路或状态管理坏了。

三层按出现时间排序:Prompt Engineering 最早,Context Engineering 2025 年中成型,Harness Engineering 2026 年初才被命名。前两层各自的技术内容在链接里,这一篇只讲它们在体系里的位置。

相关 ​

参考 ​

贡献者 ​

文件历史 ​